package com.example.yx1.demo42;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;

@Configuration
public class A42 {
    public static void main(String[] args) throws Exception{
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A42.class);
        DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();


        // 用于解析@Value
        ContextAnnotationAutowireCandidateResolver resolver = new ContextAnnotationAutowireCandidateResolver();
        resolver.setBeanFactory(beanFactory);


//        test1(context, resolver);
//        test2(context,resolver);
        test3(context,resolver,Bean4.class.getDeclaredField("value"));
    }

    private static void test1(AnnotationConfigApplicationContext context, ContextAnnotationAutowireCandidateResolver resolver) throws NoSuchFieldException {
        // 获取@Value 的内容
        Field home = Bean1.class.getDeclaredField("home");
        DependencyDescriptor dd1 = new DependencyDescriptor(home, false);
        String value1 = (String) resolver.getSuggestedValue(dd1);
        System.out.println(value1);

        value1 = context.getEnvironment().resolvePlaceholders(value1);
        System.out.println(value1);
    }

    private static void test2(AnnotationConfigApplicationContext context, ContextAnnotationAutowireCandidateResolver resolver) throws NoSuchFieldException {
        // 获取@Value 的内容
        Field age = Bean1.class.getDeclaredField("age");
        DependencyDescriptor dd1 = new DependencyDescriptor(age, false);
        String value1 = (String) resolver.getSuggestedValue(dd1);
        System.out.println(value1);

        value1 = context.getEnvironment().resolvePlaceholders(value1);
        Object age1 = context.getBeanFactory().getTypeConverter().convertIfNecessary(value1, dd1.getDependencyType());
        System.out.println(age1);
    }


    private static void test3(AnnotationConfigApplicationContext context, ContextAnnotationAutowireCandidateResolver resolver,Field field) throws NoSuchFieldException {
        // 获取@Value 的内容
        DependencyDescriptor dd1 = new DependencyDescriptor(field, false);
        String value1 =  resolver.getSuggestedValue(dd1).toString();
        System.out.println(value1);

        value1 = context.getEnvironment().resolvePlaceholders(value1);
        System.out.println(value1);

        // 解析 SpEL，即 #{}
        Object bean3 = context.getBeanFactory().getBeanExpressionResolver().evaluate(value1, new BeanExpressionContext(context.getBeanFactory(), null));
        System.out.println(bean3);
        // 进行可能需要的类型转换
        Object age1 = context.getBeanFactory().getTypeConverter().convertIfNecessary(bean3, dd1.getDependencyType());
        System.out.println(age1);
    }

    public class Bean1 {
        @Value("${JAVA_HOME}")
        private String home;

        @Value("18")
        private int age;
    }

    public class Bean2 {
        @Value("#{@bean3}") // SpringEL SpEL 表达式形式： #{SpEL},@表示根据名字找
        private Bean3 bean3;
    }

    @Component("bean3")
    public class Bean3 {}

    static class Bean4 {
        @Value("#{'hello, ' + '${JAVA_HOME}'}")
        private String value;
    }
}
